fiptool: Enable Visual Studio build
authorEvan Lloyd <[email protected]>
Thu, 25 May 2017 18:16:53 +0000 (19:16 +0100)
committerEvan Lloyd <[email protected]>
Tue, 17 Oct 2017 11:14:20 +0000 (12:14 +0100)
Updates are required to enable the fiptool utility to be built on a
Windows platform.  This change modifies the source files to enable
building with Visual Studio (detected via preprocessor settings).
The primary changes are:
  1.  Provide an implementation of the getopt_long function.  This does
      not exist in the Visual Studio CRT libraries because Windows
      commands normally use '/' not '-' as an option indicator.
  2.  Redirect some function names to match those supported by the
      Visual Studio libraries (when building with Visual Studio).
  2.  Modify a structure name (stat) to match that provided
      by the Visual Studio libraries (_stat).

Note - this change does not provide makefile updates.  It only modifies
       the sources to enable the fiptool to be built from a Visual
       Studio project.  In normal use the presence of FIPTOOL.EXE is
       enough to satisfy the make requirements.  A makefile change may
       be derived from the Visual Studio command line information at
       some point in the future.

Change-Id: I3ade77ea140246af3c030920b3f97c070087f111
Signed-off-by: Evan Lloyd <[email protected]>
tools/fiptool/fiptool_platform.h
tools/fiptool/win_posix.c [new file with mode: 0644]
tools/fiptool/win_posix.h [new file with mode: 0644]

index bfdd1efc35f71d2b21d8a1b409d064a35abde277..fd0a12048d1180fdd371c8415f98d12f43a76e7d 100644 (file)
@@ -23,6 +23,7 @@
 #      else
 
                /* Visual Studio. */
+#              include "win_posix.h"
 
 #      endif
 
diff --git a/tools/fiptool/win_posix.c b/tools/fiptool/win_posix.c
new file mode 100644 (file)
index 0000000..48feb16
--- /dev/null
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+
+#include "win_posix.h"
+
+/*
+ * This variable is set by getopt to the index of the next element of the
+ * argv array to be processed. Once getopt has found all of the option
+ * arguments, you can use this variable to determine where the remaining
+ * non-option arguments begin. The initial value of this variable is 1.
+ */
+int optind = 1;
+
+/*
+ * If the value of this variable is nonzero, then getopt prints an error
+ * message to the standard error stream if it encounters an unknown option
+ * default character or an option with a missing required argument.
+ * If you set this variable to zero, getopt does not print any messages,
+ * but it still returns the character ? to indicate an error.
+ */
+const int opterr; /* = 0; */
+/* const because we do not implement error printing.*/
+/* Not initialised to conform with the coding standard. */
+
+/*
+ * When getopt encounters an unknown option character or an option with a
+ * missing required argument, it stores that option character in this
+ * variable.
+ */
+int optopt;    /* = 0; */
+
+/*
+ * This variable is set by getopt to point at the value of the option
+ * argument, for those options that accept arguments.
+ */
+char *optarg;  /* = 0; */
+
+enum return_flags {
+       RET_ERROR = -1,
+       RET_END_OPT_LIST = -1,
+       RET_NO_PARAM = '?',
+       RET_NO_PARAM2 = ':',
+       RET_UNKNOWN_OPT = '?'
+};
+
+/*
+ * Common initialisation on entry.
+ */
+static
+void getopt_init(void)
+{
+       optarg = (char *)0;
+       optopt = 0;
+       /* optind may be zero with some POSIX uses.
+        * For our purposes we just change it to 1.
+        */
+       if (optind == 0)
+               optind = 1;
+}
+
+/*
+ * Common handling for a single letter option.
+ */
+static
+int getopt_1char(int argc,
+                char *const argv[],
+                const char *const opstring,
+                const int optchar)
+{
+       size_t nlen = (opstring == 0) ? 0 : strlen(opstring);
+       size_t loptn;
+
+       for (loptn = 0; loptn < nlen; loptn++) {
+               if (optchar == opstring[loptn]) {
+                       if (opstring[loptn + 1] == ':') {
+                               /* Option has argument */
+                               if (optind < argc) {
+                                       /* Found argument. */
+                                       assert(argv != 0);
+                                       optind++;
+                                       optarg = argv[optind++];
+                                       return optchar;
+                               }
+                               /* Missing argument. */
+                               if (opstring[loptn + 2] == ':') {
+                                       /* OK if optional "x::". */
+                                       optind++;
+                                       return optchar;
+                               }
+                               /* Actual missing value. */
+                               optopt = optchar;
+                               return ((opstring[0] == ':')
+                                       ? RET_NO_PARAM2
+                                       : RET_NO_PARAM);
+                       }
+                       /* No argument, just return option char */
+                       optind++;
+                       return optchar;
+               }
+       }
+       /*
+        * If getopt finds an option character in argv that was not included in
+        * options, ... it returns '?' and sets the external variable optopt to
+        * the actual option character.
+        */
+       optopt = optchar;
+       return RET_UNKNOWN_OPT;
+}
+
+int getopt(int argc,
+          char *argv[],
+          char *opstring)
+{
+       int result = RET_END_OPT_LIST;
+       size_t argn = 0;
+       size_t nlen = strlen(opstring);
+
+       getopt_init();
+       /* If we have an argument left to play with */
+       if ((argc > optind) && (argv != 0)) {
+               const char *arg = (const char *)argv[optind];
+
+               if ((arg != 0) && (arg[0] == '-'))
+                       result = getopt_1char(argc, argv, opstring, arg[1]);
+       }
+
+       return result;
+}
+
+/*
+ * Match an argument value against an option name.
+ * Note that we only match over the shorter length of the pair, to allow
+ * for abbreviation or say --match=value
+ * Long option names may be abbreviated if the abbreviation is unique or an
+ * exact match for some defined option.
+ * A long option may take a parameter, of the form --opt=param or --opt param.
+*/
+static
+int optmatch(const char *argval, const char *optname)
+{
+       int result = 0;
+
+       while ((result == 0) && (*optname != 0) && (*argval != 0))
+               result = (*argval++) - (*optname++);
+       return result;
+}
+
+/* Handling for a single long option. */
+static
+int getopt_1long(const int argc,
+                char *const argv[],
+                const struct option *const longopts,
+                const char *const optname,
+                int *const indexptr)
+{
+       int result = RET_UNKNOWN_OPT;
+       size_t loptn = 0;
+
+       while (longopts[loptn].name != 0) {
+               if (optmatch(optname, longopts[loptn].name) == 0) {
+                       /* We found a match. */
+                       result = longopts[loptn].val;
+                       if (indexptr != 0)
+                               *indexptr = loptn;
+                       switch (longopts[loptn].has_arg) {
+                       case required_argument:
+                               if ((optind + 1) >= argc) {
+                                       /* Missing argument. */
+                                       optopt = result;
+                                       return RET_NO_PARAM;
+                               }
+                               /* Fallthrough to get option value. */
+
+                       case optional_argument:
+                               if ((argc - optind) > 0) {
+                                       /* Found argument. */
+                                       optarg = argv[++optind];
+                               }
+                               /* Fallthrough to handle flag. */
+
+                       case no_argument:
+                               optind++;
+                               if (longopts[loptn].flag != 0) {
+                                       *longopts[loptn].flag = result;
+                                       result = 0;
+                               }
+                               break;
+
+                       }
+                       return result;
+               }
+               ++loptn;
+       }
+       /*
+        * If getopt finds an option character in argv that was not included
+        * in options, ... it returns '?' and sets the external variable
+        * optopt to the actual option character.
+        */
+       return RET_UNKNOWN_OPT;
+}
+
+/*
+ * getopt_long gets the next option argument from the argument list
+ * specified by the argv and argc arguments.  Options may be either short
+ * (single letter) as for getopt, or longer names (preceded by --).
+ */
+int getopt_long(int argc,
+               char *argv[],
+               const char *shortopts,
+               const struct option *longopts,
+               int *indexptr)
+{
+       int result = RET_END_OPT_LIST;
+
+       getopt_init();
+       /* If we have an argument left to play with */
+       if ((argc > optind) && (argv != 0)) {
+               const char *arg = argv[optind];
+
+               if ((arg != 0) && (arg[0] == '-')) {
+                       if (arg[1] == '-') {
+                               /* Looks like a long option. */
+                               result = getopt_1long(argc,
+                                                     argv,
+                                                     longopts,
+                                                     &arg[2],
+                                                     indexptr);
+                       } else {
+                               result = getopt_1char(argc,
+                                                     argv,
+                                                     shortopts,
+                                                     arg[1]);
+                       }
+               }
+       }
+       return result;
+}
+
+/*
+ * getopt_long_only gets the next option argument from the argument list
+ * specified by the argv and argc arguments.  Options may be either short
+ * or long as for getopt_long, but the long names may have a single '-'
+ * prefix too.
+ */
+int getopt_long_only(int argc,
+                    char *argv[],
+                    const char *shortopts,
+                    const struct option *longopts,
+                    int *indexptr)
+{
+       int result = RET_END_OPT_LIST;
+
+       getopt_init();
+       /* If we have an argument left to play with */
+       if ((argc > optind) && (argv != 0)) {
+               const char *arg = argv[optind];
+
+               if ((arg != 0) && (arg[0] == '-')) {
+                       if (arg[1] == '-') {
+                               /* Looks like a long option. */
+                               result = getopt_1long(argc,
+                                                     argv,
+                                                     longopts,
+                                                     &arg[2],
+                                                     indexptr);
+                       } else {
+                               result = getopt_1long(argc,
+                                                     argv,
+                                                     longopts,
+                                                     &arg[1],
+                                                     indexptr);
+                               if (result == RET_UNKNOWN_OPT) {
+                                       result = getopt_1char(argc,
+                                                             argv,
+                                                             shortopts,
+                                                             arg[1]);
+                               }
+                       }
+               }
+       }
+       return result;
+}
diff --git a/tools/fiptool/win_posix.h b/tools/fiptool/win_posix.h
new file mode 100644 (file)
index 0000000..c3fc399
--- /dev/null
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __WINPOSIX_H__
+#      define __WINPOSIX_H__
+
+#      define _CRT_SECURE_NO_WARNINGS
+
+#      include <direct.h>
+#      include <io.h>
+#      include <stdint.h>
+#      include <stdlib.h>
+#      include <string.h>
+#      include <sys/stat.h>
+
+#      include "uuid.h"
+
+
+/* Derive or provide Windows equivalents of Posix/GCC/Unix stuff. */
+#      ifndef PATH_MAX
+#              ifdef MAX_PATH
+#                      define PATH_MAX MAX_PATH
+#              else
+#                      ifdef _MAX_PATH
+#                              define MAX_PATH _MAX_PATH
+#                              define PATH_MAX _MAX_PATH
+#                      else
+#                              define PATH_MAX 260
+#                      endif
+#              endif
+#      endif
+
+#      ifndef _CRT_SECURE_NO_WARNINGS
+#              define _CRT_SECURE_NO_WARNINGS 1
+#      endif
+
+/*
+ * Platform specific names.
+ *
+ * Visual Studio deprecates a number of POSIX functions and only provides
+ * ISO C++ compliant alternatives (distinguished by their '_' prefix).
+ * These macros help provide a stopgap for that.
+ */
+
+/* fileno cannot be an inline function, because _fileno is a macro. */
+#      define fileno(fileptr) _fileno(fileptr)
+
+/* _fstat uses the _stat structure, not stat. */
+#      define BLD_PLAT_STAT    _stat
+
+/* Define flag values for _access. */
+#      define F_OK     0
+
+
+/* getopt implementation for Windows: Data. */
+
+/* Legitimate values for option.has_arg. */
+enum has_arg_values {
+       no_argument,            /* No argument value required */
+       required_argument,      /* value must be specified. */
+       optional_argument       /* value may be specified. */
+};
+
+/* Long option table entry for get_opt_long. */
+struct option {
+       /* The name of the option. */
+       const char *name;
+
+       /*
+        * Indicates whether the option takes an argument.
+        * Possible values: see has_arg_values above.
+        */
+       int has_arg;
+
+       /* If not null, when option present, *flag is set to val. */
+       int *flag;
+
+       /*
+        * The value associated with this option to return
+        * (and save in *flag when not null)
+        */
+       int val;
+};
+
+/*
+ * This variable is set by getopt to point at the value of the option
+ * argument, for those options that accept arguments.
+ */
+extern char *optarg;
+
+/*
+ * When this variable is not zero, getopt emits an error message to stderr
+ * if it encounters an unspecified option, or a missing argument.
+ * Otherwise no message is reported.
+ */
+extern const int opterr;       /* const as NOT used in this implementation. */
+
+/*
+ * This variable is set by getopt to the index of the next element of the
+ * argv array to be processed. Once getopt has found all of the option
+ * arguments, you can use this variable to determine where the remaining
+ * non-option arguments begin. The initial value of this variable is 1.
+ */
+extern int optind;
+
+/*
+ * When getopt encounters an unknown option character or an option with a
+ * missing required argument, it stores that option character in this
+ * variable.
+ */
+extern int optopt;
+
+
+/*
+ * Platform specific names.
+ *
+ * Visual Studio deprecates a number of POSIX functions and only provides
+ * ISO C++ compliant alternatives (distinguished by their '_' prefix).
+ * These inline functions provide a stopgap for that.
+ */
+
+inline int access(const char *path, int mode)
+{
+       return _access(path, mode);
+}
+
+inline int chdir(const char *s)
+{
+       return _chdir(s);
+}
+
+inline int fstat(int fd, struct _stat *buffer)
+{
+       return _fstat(fd, buffer);
+}
+
+inline char *strdup(const char *s)
+{
+       return _strdup(s);
+}
+
+/*
+ * getopt implementation for Windows: Functions.
+ *
+ * Windows does not have the getopt family of functions, as it normally
+ * uses '/' instead of '-' as the command line option delimiter.
+ * These functions provide a Windows version that  uses '-', which precludes
+ * using '-' as the intial letter of a program argument.
+ * This is not seen as a problem in the specific instance of fiptool,
+ * and enables existing makefiles to work on a Windows build environment.
+ */
+
+/*
+ * The getopt function gets the next option argument from the argument list
+ * specified by the argv and argc arguments.
+ */
+int getopt(int argc,
+          char *argv[],
+          char *options);
+
+/*
+ * getopt_long gets the next option argument from the argument list
+ * specified by the argv and argc arguments.  Options may be either short
+ * (single letter) as for getopt, or longer names (preceded by --).
+ */
+int getopt_long(int argc,
+               char *argv[],
+               const char *shortopts,
+               const struct option *longopts,
+               int *indexptr);
+
+/*
+ * getopt_long_only gets the next option argument from the argument list
+ * specified by the argv and argc arguments.  Options may be either short
+ * or long as for getopt_long, but the long names may have a single '-'
+ * prefix, too.
+ */
+int getopt_long_only(int argc,
+                          char *argv[],
+                          const char *shortopts,
+                          const struct option *longopts,
+                          int *indexptr);
+
+#endif /* __WINPOSIX_H__ */